﻿#pragma once

#include <learn/topo/topo_all.h>

#include <deque>

namespace xi
{

namespace topo
{

class Topo_Explorer
{
  public:
    /**
     * @brief 获得起始点
     *
     * @param[in] co
     * @return VertexHandle
     */
    static VHandle start_vertex(CHandle co);

    /**
     * @brief 获得目标点
     *
     * @param[in] co
     * @return VertexHandle
     */
    static VHandle end_vertex(CHandle co);

    /**
     * @brief 获得一个面上的所有顶点（不包括其它 loop）（保顺序，逆时针）
     *
     * @param[in] f
     * @return std::vector<VHandle>
     */
    static std::vector<VHandle> vertices_on_face(FHandle f);

    /**
     * @brief 获得一个面上的所有边（不包括其它 loop）（保顺序，逆时针）
     *
     * @param[in] f
     * @return std::vector<EHandle>
     */
    static std::vector<EHandle> edges_on_face(FHandle f);

    /**
     * @brief 获得一个面上的所有 coedge（不包括其它 loop）（保顺序，逆时针）
     *
     * @param[in] f
     * @return std::vector<CHandle>
     */
    static std::vector<CHandle> coedges_on_face(FHandle f);

    /**
     * @brief 获取两个顶点的一条 coedge，从 v0 出发
     *
     * @param[in] v0
     * @param[in] v1
     * @return CHandle
     */
    static CHandle common_coedge(VHandle v0, VHandle v1);

    /**
     * @brief 获得两个顶点的一条边
     *
     * @param[in] v0
     * @param[in] v1
     * @return EHandle
     */
    static EHandle common_edge(VHandle v0, VHandle v1);

    /**
     * @brief 获取两个面的公共边（保顺序，关于 f0 逆时针）
     *
     * @param[in] f0
     * @param[in] f1
     * @return std::vector<EHandle>
     */
    static std::vector<EHandle> common_edges(FHandle f0, FHandle f1);

    /**
     * @brief 获得 v 相邻的所有顶点（不保顺序）
     *
     * @param[in] v
     * @return std::unordered_set<VHandle>
     */
    static std::unordered_set<VHandle> adjacent_vertices(VHandle v);

    /**
     * @brief 获得离开 v 的所有 coedge（不保顺序）
     *
     * @param[in] v
     * @return std::unordered_set<CHandle>
     */
    static std::unordered_set<CHandle> adjacent_coedges(VHandle v);

    /**
     * @brief 获得 e 相邻的所有边（不保顺序）
     *
     * @param[in] e
     * @return std::unordered_set<EHandle>
     */
    static std::unordered_set<EHandle> adjacent_edges(EHandle e);

    /**
     * @brief 获得 v 相邻的所有面（不保顺序）
     *
     * @param[in] v
     * @return std::unordered_set<FHandle>
     */
    static std::unordered_set<FHandle> adjacent_faces(VHandle v);

    /**
     * @brief 获得 f 相邻的所有面（不保顺序）
     *
     * @param[in] f
     * @return std::unordered_set<FHandle>
     */
    static std::unordered_set<FHandle> adjacent_faces(FHandle f);

    /**
     * @brief 获得 co 所在流形的所有边（保顺序，逆时针）
     *
     * @param[in] co
     * @return std::deque<EHandle>
     */
    static std::deque<EHandle> adjacent_ordered_edges(CHandle co);

    /**
     * @brief 获得 wire 上的所有 coedge（按照 wire 中 coedge 的连接顺序）
     *
     * @param[in] wire
     * @return std::unordered_set<CHandle>
     */
    static std::unordered_set<CHandle> edges(Topo_Wire *wire);

    /**
     * @brief 获得 face 上的所有 wire（按照 face 中 loop 的嵌套顺序）
     *
     * @param[in] face
     * @return std::unordered_set<Topo_Wire *>
     */
    static std::unordered_set<Topo_Wire *> wires(Topo_Face *face);

    /**
     * @brief 获得 shell 上的所有 wire，不包括 face 上的 wire
     *
     * @param[in] shell
     * @return std::unordered_set<Topo_Wire *>
     */
    static std::unordered_set<Topo_Wire *> wires(Topo_Shell *shell);

    /**
     * @brief 获得 shell 上的所有 face
     *
     * @param[in] shell
     * @return std::unordered_set<Topo_Face *>
     */
    static std::unordered_set<Topo_Face *> faces(Topo_Shell *shell);
};

} // namespace topo

} // namespace xi
